package com.ijiuchuang.jc_localization.ble;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.text.TextUtils;
import android.widget.Toast;

import com.ijiuchuang.jc_localization.tools.utils.HexUtil;
import com.ijiuchuang.jc_localization.tools.utils.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class BluetoothLeService extends Service {

    private final static String TAG = BluetoothLeService.class.getSimpleName();

    private BluetoothManager mBluetoothManager;
    // BT 适配器
    private BluetoothAdapter mBluetoothAdapter;
    public BluetoothGatt mBluetoothGatt;

    public final static UUID UUID_CHZU_SERIAL_PORT_CHAR =
            UUID.fromString("0000fff4-0000-1000-8000-00805f9b34fb");
    public final static UUID UUID_CHZU_SERIAL_PORT_CHAR_READ =
            UUID.fromString("0000fff1-0000-1000-8000-00805f9b34fb");
    public final static UUID UUID_CHZU_SERIAL_PORT_SERVICE =
            UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");

    private BluetoothGattCharacteristic mSerialDataChar = null;
    private BluetoothGattCharacteristic mWriteDataChar = null;

    // 过滤机制
    private String FilterBluetooth = BluetoothAdapter.ACTION_STATE_CHANGED;

    private BluetoothLeStateListener leStateListener;

    private ArrayList<BluetoothDevice> scanList = new ArrayList<>();


    public BluetoothLeService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        //实例化过滤器并设置要过滤的广播
        IntentFilter bluetoothIntentFilter = new IntentFilter(FilterBluetooth);
        //注册广播
        leStateListener = new BluetoothLeStateListener();
        this.registerReceiver(leStateListener, bluetoothIntentFilter);

        if (initialize()) {
            if (!mBluetoothAdapter.isEnabled()) {
                // 蓝牙未打开
                Toast.makeText(this, "请打开蓝牙", Toast.LENGTH_SHORT).show();
            } else {
                //开启扫描
                scanLeDevice(true);
            }
        } else {
            Toast.makeText(this, "请确认:\n1. 蓝牙功能正常\n2. 支持蓝牙4.0\n否则将无法使用部分功能!!!", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 扫描回调 - Bluetooth
     */
    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            // 数据处理
            iBeaconClass.dataProcessing(device, rssi, scanRecord);
        }
    };

    /**
     * GATT 回调
     */
    private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        //状态改变时调用
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            switch (newState) {
                case BluetoothProfile.STATE_CONNECTING:
                    // 连接中
                    Log.i("连接中");
                    break;
                case BluetoothProfile.STATE_CONNECTED:
                    // 已连接
                    Log.i("已连接 " + gatt.getDevice().getAddress());
                    mBluetoothGatt.discoverServices();
                    break;
                case BluetoothProfile.STATE_DISCONNECTED:
                    // 已断开
                    Log.i("已断开");
                    break;
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                List<BluetoothGattService> gattServices = mBluetoothGatt.getServices();
                for (BluetoothGattService gattService : gattServices) {
                    //Log.i("222 uuid:"+gattService.getUuid()+",type:"+gattService.getType()+",InstanceId:"+gattService.getInstanceId());
                    //Log.i("333 Characteristics:"+gattService.getCharacteristics());
                    for (BluetoothGattCharacteristic bbbb : gattService.getCharacteristics()){
                        //Log.i("444 - uuid:" + bbbb.getUuid() + ", Properties:" + bbbb.getProperties());
                    }
                    if(UUID_CHZU_SERIAL_PORT_SERVICE.equals(gattService.getUuid()))
                    {
                        // 只需要发送数据
                        mSerialDataChar = gattService.getCharacteristic(UUID_CHZU_SERIAL_PORT_CHAR);
                        mWriteDataChar = gattService.getCharacteristic(UUID_CHZU_SERIAL_PORT_CHAR_READ);

                        writeCharacteristic(new byte[]{1});
                        if (null != mBluetoothGatt && null != mBluetoothAdapter) {
                            setCharacteristicNotification(mSerialDataChar, true);
                            //mBluetoothGatt.readCharacteristic(mSerialDataChar);
                            Log.i("000");
                        }
                    }
                }
            } else {
                Log.i(TAG, "onServicesDiscovered received: " + status);
            }
        }

        // 读到数据时调用
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.i("有数据来了 Read");
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            Log.i("有数据来了 Changed - " + HexUtil.encodeHexStr(characteristic.getValue()));
        }

        // 发送数据
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.i("发送数据: " + status);
            disconnect();
        }
    };

    /**
     * 写数据
     * @param data
     */
    private void writeCharacteristic(byte[] data) {
        if (mBluetoothGatt != null && mBluetoothAdapter != null) {
            mWriteDataChar.setValue(data);
            mBluetoothGatt.writeCharacteristic(mWriteDataChar);
        }
    }

    public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
        if (null == mBluetoothAdapter || null == mBluetoothGatt) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
        List<BluetoothGattDescriptor> descriptors=characteristic.getDescriptors();
        for(BluetoothGattDescriptor dp:descriptors) {
            dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            mBluetoothGatt.writeDescriptor(dp);
        }
    }

    /**
     * 连接
     * @param device
     * @return
     */
    private boolean connect(BluetoothDevice device) {
        if (mBluetoothAdapter == null || device == null) {
            return false;
        }
        mBluetoothGatt = device.connectGatt(this, false, gattCallback);
        return true;
    }

    private boolean connect(String  mac) {
        if (mBluetoothAdapter == null || mac == null || scanList.isEmpty()) {
            return false;
        }
        int i = 0;
        for ( ; i < scanList.size(); i++) {
            if (scanList.get(i).getAddress().equals(mac)) {
                break;
            }
        }
        mBluetoothGatt = scanList.get(i).connectGatt(this, false, gattCallback);
        return true;
    }

    /**
     * 断开连接
     */
    private void disconnect() {
        if (null != mBluetoothGatt)
            mBluetoothGatt.disconnect();
    }

    /**
     * 开启扫描
     * @param enable
     */
    private void scanLeDevice(final boolean enable) {
        if (enable) {
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

    /**
     * 初始化 蓝牙
     * @return Return true if the initialization is successful.
     */
    public boolean initialize() {
        // For API level 18 and above, get a reference to BluetoothAdapter through
        // BluetoothManager.
        if (mBluetoothManager == null) {
            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            if (mBluetoothManager == null) {
                Log.e("Unable to initialize BluetoothManager.");
                return false;
            }
        }

        mBluetoothAdapter = mBluetoothManager.getAdapter();
        if (mBluetoothAdapter == null) {
            Log.e("Unable to obtain a BluetoothAdapter.");
            return false;
        }

        return true;
    }

    /**
     * 监听蓝牙状态
     * 当蓝牙开启时: 启动扫描
     * 当蓝牙关闭时: 关闭扫描, 并提醒用户 - toast
     */
    private class BluetoothLeStateListener extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // 蓝牙状态发生改变
            if (TextUtils.equals(BluetoothAdapter.ACTION_STATE_CHANGED, action)) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                switch (state) {
                    case BluetoothAdapter.STATE_TURNING_ON:             //打开中
                        break;
                    case BluetoothAdapter.STATE_ON:                     //已打开
                        // 开启扫描
                        scanLeDevice(true);
                        break;
                    case BluetoothAdapter.STATE_TURNING_OFF:            //关闭中
                        Toast.makeText(
                                getApplicationContext(),
                                "关闭蓝牙将无法使用部分功能",
                                Toast.LENGTH_LONG).show();
                        // 关闭扫描
                        scanLeDevice(false);
                        break;
                    case BluetoothAdapter.STATE_OFF:                    //已关闭
                        // 确认关闭扫描
                        scanLeDevice(false);
                        break;
                }
            }
        }
    }
}
